Add COLLECT reducer to FT.AGGREGATE#524
Conversation
Introduce the COLLECT reducer for FT.AGGREGATE GROUPBY, which gathers per-document projections within each group and returns them as an array of per-entry maps under the reducer alias, optionally sorted and bounded. - Add CollectReducer with Fields(...)/FieldsAll(), SortBy(...)/SortByAsc/ SortByDesc, Limit(...) and As(...), plus the Reducers.Collect() factory. Field and sort names are normalized to a single '@' prefix on the wire, and <narg> covers the FIELDS/SORTBY/LIMIT tokens (excluding AS <alias>), matching the RediSearch grammar. Nested COLLECT columns are read through the existing AggregationResult parsing across RESP2 and RESP3. - Register the new public API symbols in PublicAPI.Unshipped.txt. COLLECT is experimental and gated behind search-enable-unstable-features on the server.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b630fd1. Configure here.
| /// Configure the reducer fully before attaching it to a <c>GROUPBY</c>: <see cref="AggregationRequest.GroupBy(string, Reducer[])"/> | ||
| /// serializes the reducer immediately, so builder calls made after that point cannot reach the wire and throw | ||
| /// <see cref="InvalidOperationException"/>. | ||
| /// </para> |
There was a problem hiding this comment.
As after GroupBy silently ignored
Medium Severity
CollectReducer documentation states that builder calls after GroupBy throw, but inherited As does not use EnsureMutable. Calling As after the reducer is serialized updates Alias on the object while the aggregation args list stays unchanged, so results are read under the wrong key without an error.
Reviewed by Cursor Bugbot for commit b630fd1. Configure here.
| { | ||
| var server = redis.GetServer(endPoint); | ||
| if (!server.IsConnected) continue; | ||
| server.Execute("CONFIG", "SET", "search-enable-unstable-features", "yes"); |
There was a problem hiding this comment.
if these are "unstable" features, should the new APIs be marked [Experimental] ?


Introduce the COLLECT reducer for FT.AGGREGATE GROUPBY, which gathers per-document projections within each group and returns them as an array of per-entry maps under the reducer alias, optionally sorted and bounded.
COLLECT is experimental and gated behind search-enable-unstable-features on the server.
Note
Low Risk
Additive search aggregation API and tests only; no changes to auth, data paths, or existing reducer behavior.
Overview
Adds client support for the experimental REDUCE COLLECT reducer on
FT.AGGREGATEGROUPBY, so each group can return an array of per-document field maps under a reducer alias.A new
CollectReducerbuilder (viaReducers.Collect()) serializesFIELDS(explicit names or*), optional in-groupSORTBY, andLIMIT, with@normalization and<narg>matching RediSearch grammar. Configuration must finish beforeGroupByattaches the reducer; later mutations throw instead of being dropped.Public API entries are added in
PublicAPI.Unshipped.txt. Coverage includes unit tests for command args and an integration test (Redis ≥ 8.7) that enablessearch-enable-unstable-featuresand checks sort/limit behavior on grouped results.Reviewed by Cursor Bugbot for commit b630fd1. Bugbot is set up for automated code reviews on this repo. Configure here.